package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 老李头儿
 * @since 2025-03-27
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {


    private final InteractionQuestionMapper questionMapper;
    private final UserClient userClient;

    /**
     * 新增回答或评论
     *
     * @param replyDTO
     */
    @Override
    public void saveReply(ReplyDTO replyDTO) {
        //属性拷贝
        InteractionReply interactionReply = BeanUtil.toBean(replyDTO, InteractionReply.class);
        interactionReply.setUserId(UserContext.getUser());
        //写入数据库
        save(interactionReply);

        //判断是否是回答
        if (replyDTO.getAnswerId() == null) {
            //如果是回答，修改问题表的最近一次回答的id
            LambdaUpdateWrapper<InteractionQuestion> updateWrapper = new LambdaUpdateWrapper<>();

            updateWrapper.set(InteractionQuestion::getLatestAnswerId, interactionReply.getId())
                    .setSql("answer_times = answer_times + 1")
                    .eq(InteractionQuestion::getId, replyDTO.getQuestionId());
            questionMapper.update(null, updateWrapper);
        } else {
            //如果是评论，修改回答的评论数量
            this.lambdaUpdate()
                    .setSql("reply_times = reply_times + 1")
                    .eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .update();
        }

        if (replyDTO.getIsStudent()) {
            //修改状态为未查看
            LambdaUpdateWrapper<InteractionQuestion> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(InteractionQuestion::getStatus, 0)
                    .eq(InteractionQuestion::getId, replyDTO.getQuestionId());
            questionMapper.update(null, updateWrapper);
        }
    }

    /**
     * 分页查询回答或评论列表
     *
     * @param replyPageQuery
     */
    @Override
    public PageDTO<ReplyVO> pageReply(ReplyPageQuery replyPageQuery, boolean isAdmin) {
        if (ObjectUtil.isEmpty(replyPageQuery.getQuestionId()) && ObjectUtil.isEmpty(replyPageQuery.getAnswerId())) {
            throw new BadRequestException("问题id与回答Id查询参数不能都为空");
        }
        //查询所有的回答
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(replyPageQuery.getQuestionId() != null, InteractionReply::getQuestionId, replyPageQuery.getQuestionId())
                .eq(replyPageQuery.getAnswerId() == null, InteractionReply::getAnswerId, 0)
                .eq(replyPageQuery.getAnswerId() != null, InteractionReply::getAnswerId, replyPageQuery.getAnswerId())
                .eq(!isAdmin, InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPage(new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)));

        List<InteractionReply> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        //收集所有userid
        Set<Long> userIds = records.stream().map(InteractionReply::getUserId).collect(Collectors.toSet());
        //查询用户信息
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        //转为map
        Map<Long, UserDTO> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        ArrayList<ReplyVO> vos = new ArrayList<>();
        for (InteractionReply record : records) {
            ReplyVO vo = BeanUtil.toBean(record, ReplyVO.class);
            if (isAdmin) {
                vo.setUserIcon(userMap.get(record.getUserId()).getIcon());
                vo.setUserName(userMap.get(record.getUserId()).getName());
            } else {
                if (!record.getAnonymity()) {
                    vo.setUserIcon(userMap.get(record.getUserId()).getIcon());
                    vo.setUserName(userMap.get(record.getUserId()).getName());
                }
            }
            if (record.getTargetReplyId() != 0){
                vo.setTargetUserName(userMap.get(record.getTargetUserId()).getName());
            }
            vos.add(vo);
        }
        return PageDTO.of(page, vos);
    }

    /**
     * 隐藏或显示评论
     *
     * @param id
     * @param hidden
     */
    @Override
    @Transactional
    public void isHidden(Long id, boolean hidden) {
        // 1.查询
        InteractionReply old = getById(id);
        if (old == null) {
            return;
        }

        // 2.隐藏回答
        InteractionReply reply = new InteractionReply();
        reply.setId(id);
        reply.setHidden(hidden);
        updateById(reply);

        // 3.隐藏评论，先判断是否是回答，回答才需要隐藏下属评论
        if (old.getAnswerId() != null && old.getAnswerId() != 0) {
            // 3.1.有answerId，说明自己是评论，无需处理
            return;
        }
        // 3.2.没有answerId，说明自己是回答，需要隐藏回答下的评论
        lambdaUpdate()
                .set(InteractionReply::getHidden, hidden)
                .eq(InteractionReply::getAnswerId, id)
                .update();

    }
}
